package main

import (
	"bytes"
	_ "embed"
	"fmt"
	"io"
	"os"
	"regexp"
	"strconv"
	"strings"
	"time"

	"fyne.io/fyne/v2/data/binding"

	"github.com/adrg/sysfont"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/dialog"

	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/widget"
)

const howto = `在“记录”或者“运行”时，点击鼠标右键即结束该任务。
Right click to end the task while recording or running.
`

func getFont() string {
	words := []string{"song", "fangsong", "kai", "hei"}

	opts := sysfont.FinderOpts{Extensions: []string{".ttf"}}
	finder := sysfont.NewFinder(&opts)

	for _, f := range finder.List() {
		for _, w := range words {
			if strings.Index(strings.ToLower(f.Name), w) >= 0 {
				println(w, f.Name, f.Filename)
				return f.Filename
			}
		}
	}
	return ""
}

func setFont() {
	fontpath := getFont()
	os.Setenv("FYNE_FONT", fontpath)
}

type RecordApp struct {
	App       fyne.App
	Window    fyne.Window
	NumLabel  *widget.Label
	Repeat    *widget.Entry
	BtRecord  *widget.Button
	BtPlay    *widget.Button
	RepeatNum binding.String
}

func (p *RecordApp) ShowError(err error) {
	dialog.ShowError(err, p.Window)
}

func (p *RecordApp) SaveFile(data []byte) {
	dialog.ShowFileSave(
		func(w fyne.URIWriteCloser, e error) {

			if e != nil {
				dialog.ShowError(e, p.Window)
				return
			}
			if w == nil {
				return
			}
			defer w.Close()
			buf := bytes.NewBuffer(data)
			n, err := buf.WriteTo(w)

			if err != nil {
				dialog.ShowError(err, p.Window)
				return
			}
			if n <= 0 {
				dialog.ShowError(fmt.Errorf("Nothing saved"), p.Window)
				return
			}
		},
		p.Window)
}

func (p *RecordApp) GetFile() chan []byte {
	var ret = make(chan []byte, 1)

	dialog.ShowFileOpen(
		func(r fyne.URIReadCloser, e error) {
			defer r.Close()
			data, err := io.ReadAll(r)
			if err != nil {
				dialog.ShowError(err, p.Window)
				ret <- nil
			} else {
				ret <- data
			}
			close(ret)
		},
		p.Window)
	return ret
}

var app1 = &RecordApp{}

func showGui() {
	app1.App = app.NewWithID("auto_mouse_robot")

	app1.Window = app1.App.NewWindow(T("鼠标自动机"))

	app1.NumLabel = widget.NewLabel("-")
	app1.NumLabel.Alignment = fyne.TextAlignCenter
	repeat := widget.NewLabel(T("重复次数："))
	repeat.Alignment = fyne.TextAlignTrailing
	app1.Repeat = widget.NewEntry()

	app1.RepeatNum = binding.NewString()
	app1.RepeatNum.Set("99999")
	app1.RepeatNum.AddListener(binding.NewDataListener(func() {
		r1 := regexp.MustCompile("^[0-9]+$")
		s, err := app1.RepeatNum.Get()
		if err != nil {
			dialog.ShowError(err, app1.Window)
			return
		}
		b := r1.Match([]byte(s))
		if !b {
			dialog.ShowError(fmt.Errorf(T("请输入整数")), app1.Window)
			err = app1.RepeatNum.Set("99999")
			if err != nil {
				dialog.ShowError(err, app1.Window)
				return
			}
			return
		}
	}))
	app1.Repeat.Bind(app1.RepeatNum)

	app1.BtRecord = widget.NewButton(T("记录"), func() {
		sNum, err := app1.RepeatNum.Get()
		if err != nil {
			dialog.ShowError(err, app1.Window)
			return
		}
		num, err := strconv.Atoi(sNum)
		if err != nil {
			dialog.ShowError(err, app1.Window)
			return
		}
		go record(num)

		go func() {
			for num := 3; num > 0; num-- {
				fyne.DoAndWait(func() {
					app1.NumLabel.SetText(fmt.Sprintf("%v", num))
					app1.Window.Content().Refresh()
				})

				_ = <-time.After(time.Second)
			}
			fyne.DoAndWait(func() {
				app1.NumLabel.SetText(T("开始记录"))
			})

		}()
		println("run record")
		return
	})

	recordLine := container.NewGridWithColumns(3, app1.BtRecord, repeat, app1.Repeat)

	app1.BtPlay = widget.NewButton(T("运行"), func() {
		ch := app1.GetFile()

		go func() {

			go func() {
				data := <-ch
				if data == nil {
					return
				}
				var ex = make(chan int, 1)
				var finish = make(chan int, 1)
				go func() {
					for num := 3; num > 0; num-- {
						fyne.DoAndWait(func() {
							app1.NumLabel.SetText(fmt.Sprintf("%v", num))
						})
						_ = <-time.After(time.Second)
					}
				}()
				go waitRightClick(ex, finish)
				err := play(data, ex)
				if err != nil {
					println(err.Error())
				}
				finish <- 1
				close(finish)
			}()

		}()

		return
	})

	labelHowto := widget.NewLabel(howto)

	box1 := container.NewVBox(app1.NumLabel, recordLine, app1.BtPlay, labelHowto)

	app1.Window.SetContent(box1)
	app1.Window.Resize(fyne.NewSize(400, 300))

	app1.Window.SetOnClosed(func() {
		app1.App.Quit()
	})
	app1.Window.ShowAndRun()
}

func ErrPanic(err error) {
	if err != nil {
		panic(err)
	}
}
